/*
#Copyright (c) 2013, Philippe Bordron <philippe.bordron@gmail.com>
#
# This file is part of SIPPER.
#
# DCC is free software: you can redistribute it and/or modify
# it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# DCC is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU LESSER GENERAL PUBLIC LICENSE for more details.
#
# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE
# along with SIPPER.  If not, see <http://www.gnu.org/licenses/>
*/
package combi.wip.sipper.io;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import org.jgrapht.DirectedGraph;
import org.jgrapht.graph.DefaultEdge;

import combi.sipper.modeling.distances.DistanceBetweenGenes;
import combi.sipper.modeling.distances.DistanceColocalisation;
import combi.utils.Couple;
import combi.wip.sipper.modeling.Protein;
import combi.wip.sipper.modeling.genomes.CircularGenome;
import combi.wip.sipper.modeling.genomes.Gene;
import combi.wip.sipper.modeling.genomes.Genome;
import combi.wip.sipper.modeling.integratedModel.IntegratedModel;
import combi.wip.sipper.modeling.metabolicNetwork.graphs.ReactionGraph;
import combi.wip.sipper.modeling.reactions.Reaction;

public class IObioASP {

	private static String SEPARATOR = " ";

	public void load(String fileGenome, String fileReactionGraph, String fileAsso, String fileOut, String fileOutReactions, String fileOutGenes, String fileOutAsso)throws IOException
	{
		BufferedReader in;
		String ch = null;
		List<Gene<Protein>> geneList = new LinkedList<Gene<Protein>>();
		in = new BufferedReader(new FileReader(fileGenome));
		while ((ch=in.readLine())!=null)
		{
			geneList.add(new Gene<Protein>(ch));
		}
		in.close();
		Genome<Gene<Protein>, Protein> genome = new CircularGenome<Gene<Protein>, Protein>(geneList);
		DistanceBetweenGenes<Gene<Protein>> distance = new DistanceColocalisation<Gene<Protein>, Protein>(genome);

		//Map<String, Set<Gene<Protein>>> asso = new HashMap<String, Set<Gene<Protein>>>();
		Map<String, Set<Integer>> rToID = new HashMap<String, Set<Integer>>();
		Map<String, Set<Integer>> gToID = new HashMap<String, Set<Integer>>();
		Map<Integer, Gene<Protein>> idToGene = new HashMap<Integer, Gene<Protein>>();
		Map<Integer, String> idToReaction = new HashMap<Integer, String>();
		int i = 0;
		in = new BufferedReader(new FileReader(fileAsso));
		while ((ch=in.readLine())!=null)
		{
			String[] c = ch.split("[\t ]+");
			//Set<Gene<Protein>> set = asso.get(c[0]);
			Set<Integer> ids = rToID.get(c[0]); 
			if(ids == null)
			{
				//set = new HashSet<Gene<Protein>>();
				//asso.put(c[0],set);
				ids = new HashSet<Integer>();
				rToID.put(c[0],ids);
			}
			//set.add(new Gene<Protein>(c[1]));
			ids.add(i);

			ids = gToID.get(c[1]); 
			if(ids == null)
			{
				//set = new HashSet<Gene<Protein>>();
				//asso.put(c[0],set);
				ids = new HashSet<Integer>();
				gToID.put(c[1],ids);
			}
			ids.add(i);

			idToGene.put(i, new Gene<Protein>(c[1]));
			idToReaction.put(i, c[0]);
			i++;
		}
		in.close();
		//System.err.println(i);

		BufferedWriter out;
		out = new BufferedWriter(new FileWriter(fileOut));
		in = new BufferedReader(new FileReader(fileReactionGraph));
		out.write(i+"\n\n");
		while ((ch=in.readLine())!=null)
		{
			String[] c = ch.split("[\t ]+");
			//System.err.println(c[0]+" "+ c[1]);
			for (Integer idS : rToID.get(c[0]))
			{
				for (Integer idD : rToID.get(c[1]))
				{
					out.write(idS+"\t" + idD + "\t" + distance.get(idToGene.get(idS), idToGene.get(idD)) +"\n");
				}
			}
		}
		in.close();
		out.close();


		out = new BufferedWriter(new FileWriter(fileOutReactions));
		for (Entry<String, Set<Integer>> entry : rToID.entrySet())
		{
			out.write(entry.getKey()+"\t"+entry.getValue().toString().replaceAll("\\[", "").replaceAll("\\]", "").replaceAll(",", "")+ "\n");
		}
		out.close();

		out = new BufferedWriter(new FileWriter(fileOutGenes));
		for (Entry<String, Set<Integer>> entry : gToID.entrySet())
		{
			out.write(entry.getKey()+"\t"+entry.getValue().toString().replaceAll("\\[", "").replaceAll("\\]", "").replaceAll(",", "")+ "\n");
		}
		out.close();

		out = new BufferedWriter(new FileWriter(fileOutAsso));
		for (int j = 0; j<i; j++)
		{
			Couple<String, String> p = new Couple<String, String>(idToGene.get(j).getId(), idToReaction.get(j));
			out.write(j+"\t" +p.toString() + "\n");
		}
		out.close();

	}

	public void export(IntegratedModel<Gene<Protein>, String, Reaction<String>,Protein> model, String fileOutGenome, String fileOutReaction, String fileOutAsso) throws IOException
	{
		ReactionGraph<String, Reaction<String>> reactionGraph = new ReactionGraph<String, Reaction<String>>(model.getMetabolism());
		DirectedGraph<String, DefaultEdge> graph = reactionGraph.generateGraph();
		BufferedWriter out;
		out = new BufferedWriter(new FileWriter(fileOutReaction));
		for (DefaultEdge e : graph.edgeSet())
		{
			out.write(graph.getEdgeSource(e) + SEPARATOR + graph.getEdgeTarget(e)+"\n");
		}
		out.close();
		out = new BufferedWriter(new FileWriter(fileOutGenome));
		out.write(model.getGenome().toString().replaceAll("[\\[\\]]","").replaceAll(", ","\n"));
		out.close();

		out = new BufferedWriter(new FileWriter(fileOutAsso));
		//System.err.println(model.getEnzymeSet());
		for(Reaction<String> r : model.getReactionSet())
		{
			Collection<Gene<Protein>>  gSet  = new HashSet<Gene<Protein>>();
			for (Protein e : model.getMetabolism().getEnzymes(r))
			{
				for (Protein p : e.getDeepComponents())
				{
					gSet.addAll(model.getGenome().getGenes(p));
				}
			}
			for (Gene<Protein> g : gSet)
			{
				out.write(g.getId() + SEPARATOR + r.getId()+"\n");
			}
		}
		out.close();
	}

	public static void main (String[] args)throws IOException
	{
		String prefix = args[0];
		IObioASP m = new IObioASP();
		m.load(prefix+"genome.txt",prefix+"metabolism.txt", prefix+"catalyze.txt", prefix+"modele.txt", prefix+"associationsR.txt", prefix+"associationsG.txt", prefix+"associations.txt");
	}

}
